package com.cah.game;

import java.util.HashMap;
import java.util.concurrent.ExecutionException;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.cah.library.DatabaseHelper;
import com.cah.library.UserFunctions;

import android.app.Activity;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.util.SparseArray;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;

public abstract class GameUIFragment extends Fragment
{
	String gameKey, userKey, gameName;
	JSONObject gameInfo, lastRoundInfo;
	int currentRound, blackId, pick;
	TextView previousRoundHeader, oldBlackTextView, gameHeader, blackTextView, instructionTextView;
	Button gameHistoryButton;
	MainActivity main;
	LinearLayout submissionLayout;
	FragmentManager fragmentManager;
	boolean infoSet;
	
	static final int ROUND_HISTORY_FRAGMENT = 2;
	static final String ROUND_HISTORY_FRAGMENT_TAG = "roundHistory";
	
	
	public GameUIFragment(String gameKey, JSONObject gameInfo)
	{
		super();
		this.gameKey = gameKey;
		this.gameInfo = gameInfo;
	}
	
	public GameUIFragment()
	{
		super();
		gameKey = "";
		gameInfo = null;
	}
	
	@Override
	public void onSaveInstanceState(Bundle outState)
	{
		outState.putString("gameKey", gameKey);
		outState.putString("gameInfo", gameInfo.toString());
		if(lastRoundInfo != null)
		{
			outState.putString("lastRoundInfo", lastRoundInfo.toString());
		}
	}
	
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		
		fragmentManager = getFragmentManager();
		LastRoundInfoFragment lr = (LastRoundInfoFragment)fragmentManager.findFragmentByTag(ROUND_HISTORY_FRAGMENT_TAG);
		
		if(lr != null)
		{
			lr.setTargetFragment(this, ROUND_HISTORY_FRAGMENT);
		}
	}
	
	@Override
	public void onActivityCreated(Bundle savedInstanceState)
	{
		super.onActivityCreated(savedInstanceState);
		
		infoSet = false;
		main = (MainActivity)getActivity();
		main.actionBar.setDisplayHomeAsUpEnabled(true);
		userKey = main.getUserKey();
		main.historyBackVisible = false;
		main.historyForwardVisible = false;
		main.invalidateOptionsMenu();
		
		if(savedInstanceState != null)
		{
			gameKey = savedInstanceState.getString("gameKey");
			try
			{
				gameInfo = new JSONObject(savedInstanceState.getString("gameInfo"));
				if(lastRoundInfo != null)
				{
					lastRoundInfo = new JSONObject(savedInstanceState.getString("lastRoundInfo"));
				}
			} catch (JSONException e)
			{
				e.printStackTrace();
			}
		}
		
		try
		{
			blackId = gameInfo.getInt("blackId");
			gameName = gameInfo.getString("gameName");
			currentRound = gameInfo.getInt("currentRound");
		} catch (JSONException e)
		{
			e.printStackTrace();
		}
		
		GetBlackCardInfoProcess blackProcess = new GetBlackCardInfoProcess();
		blackProcess.execute(blackId);
		

		main.setTitle(gameName);
		main.currentGameName = gameName;
		
		gameHeader = (TextView)main.findViewById(R.id.gameHeader);
		instructionTextView = (TextView)main.findViewById(R.id.instructions);
		blackTextView = (TextView)main.findViewById(R.id.blackText);
		previousRoundHeader = (TextView)main.findViewById(R.id.previousRoundHeader);
		submissionLayout = (LinearLayout)main.findViewById(R.id.submissionLinearLayout);
		gameHistoryButton = (Button)main.findViewById(R.id.gameHistoryButton);
		oldBlackTextView = (TextView)main.findViewById(R.id.oldBlackTextView);
		
		pick = 0;
		
		try
		{
			String[] blackResults = blackProcess.get();
			String blackText = blackResults[1];
			pick = Integer.parseInt(blackResults[2]);
			blackTextView.setText(blackText);
			
		} catch (InterruptedException e1)
		{
			e1.printStackTrace();
		} catch (ExecutionException e1)
		{
			e1.printStackTrace();
		}
		
			
		gameHistoryButton.setOnClickListener(new View.OnClickListener()
		{
			
			@Override
			public void onClick(View arg0)
			{
				main.startGameHistoryFragment(gameKey, 1, -1);
			}
		});
		
		if(lastRoundInfo != null)
		{
			setLastRoundInfo();
		}
		else
		{
			LastRoundInfoFragment lr = new LastRoundInfoFragment();
			lr.setTask(new LastRoundInfoProcess());
			lr.setTargetFragment(this, ROUND_HISTORY_FRAGMENT);
			lr.show(fragmentManager, ROUND_HISTORY_FRAGMENT_TAG);
		}
	}
	
	@Override
	public void onActivityResult(int requestCode, int resultCode, Intent data)
	{
		if((requestCode == ROUND_HISTORY_FRAGMENT) && (resultCode == Activity.RESULT_OK))
		{
			try
			{
				lastRoundInfo = new JSONObject(data.getStringExtra("lastRoundInfo"));
				if(lastRoundInfo.getInt("success") == 1)
				{
					setLastRoundInfo();
				}
			} catch (JSONException e)
			{
				e.printStackTrace();
			}
		}
	}
	
	protected void setLastRoundInfo()
	{
		if(!infoSet)
		{
			infoSet = true;
			int lastRound = currentRound - 1;
			if(lastRound==0)
			{
				previousRoundHeader.setText("No previous rounds yet!");
			} 
			else
			{
				try
				{
					JSONObject value = lastRoundInfo.getJSONObject("value");
					int oldBlackId = value.getInt("blackCardId");
					JSONArray submissions = value.getJSONArray("submissions");
					String oldCzar = value.getString("czar");
					String winner = value.getString("winner");
					JSONArray scores = value.getJSONArray("scores");
					
					
					GetBlackCardInfoProcess blackProcess = new GetBlackCardInfoProcess();
					blackProcess.execute((Integer)oldBlackId);
					
					HashMap<String, String> scoreMap = new HashMap<String, String>();
					
					for(int i=0;i<scores.length();i++)
					{
						JSONObject score = scores.getJSONObject(i);
						scoreMap.put(score.getString("username"), Integer.toString(score.getInt("score")));
					}
					
					String headerText = "Round " + Integer.toString(lastRound) + ": " + oldCzar + "(" + scoreMap.get(oldCzar) + ") picked.";
					previousRoundHeader.setText(headerText);
					
					String oldBlackText = blackProcess.get()[1];
					oldBlackTextView.setText(oldBlackText);
					
					for(int i=0;i<submissions.length();i++)
					{
						JSONObject submission = submissions.getJSONObject(i);
						String playerName = submission.getString("username");
						
						JSONArray cards = submission.getJSONArray("submission");
						int[] cardIdArray = new int[cards.length()];
						
						for(int j=0;j<cards.length();j++)
						{
							cardIdArray[j] = cards.getInt(j);
						}
						
						GetWhiteCardTextProcess whiteProcess = new GetWhiteCardTextProcess();
						whiteProcess.execute(cardIdArray);
						
						SparseArray<String> cardIdTextMap = whiteProcess.get();
						
						String submissionText = playerName + "(" + scoreMap.get(playerName) + ")  submitted: ";
						
						for(int j=0;j<cardIdArray.length;j++)
						{
							if(j>0)
							{
								submissionText += ", ";
							}
							
							submissionText += cardIdTextMap.get(cardIdArray[j]);
						}
						
						TextView submissionTextView = new TextView(main);
						submissionTextView.setBackgroundColor(getResources().getColor(R.color.white));
	
						submissionTextView.setTextColor(getResources().getColor(R.color.gray));
						if(playerName.equals(winner))
						{
	
							submissionTextView.setTextColor(getResources().getColor(R.color.black));
							submissionTextView.setBackground(getResources().getDrawable(R.drawable.back));
						}
						
						submissionTextView.setText(submissionText);
						int padding = main.pxToDp(1);
						submissionTextView.setPadding(padding, padding, padding, padding);
						
						submissionLayout.addView(submissionTextView);
					}
				} catch (JSONException e)
				{
					e.printStackTrace();
				} catch (InterruptedException e)
				{
					e.printStackTrace();
				} catch (ExecutionException e)
				{
					e.printStackTrace();
				}
			}
		}
	}
	
	protected class GetWhiteCardTextProcess extends AsyncTask<int[], Void, SparseArray<String>>
	{

		@Override
		protected SparseArray<String> doInBackground(int[]... params)
		{
			SparseArray<String> map = new SparseArray<String>();
			int[] ids = params[0];
			DatabaseHelper mydbhelper = new DatabaseHelper(main);
			Cursor c = mydbhelper.getWhiteTexts(ids);
			
			while(c.moveToNext())
			{
				map.put(c.getInt(c.getColumnIndex("_id")), c.getString(c.getColumnIndex("text")));
			}
			
			return map;
		}
	}
	
	//Returns {_id, text, pick}
	protected class GetBlackCardInfoProcess extends AsyncTask<Integer, Void, String[]>
	{
		@Override
		protected String[] doInBackground(Integer... params)
		{
			int id = params[0].intValue();
			DatabaseHelper mydbhelper = new DatabaseHelper(main);
			Cursor c = mydbhelper.getBlackCard(id);
			c.moveToFirst();
			String[] result = new String[3];
			result[0] = c.getString(c.getColumnIndex("_id"));
			result[1] = c.getString(c.getColumnIndex("text"));
			result[2] = c.getString(c.getColumnIndex("pick"));
			return result;
		}
		
	}
	
	public static class LastRoundInfoFragment extends DialogFragment
	{
		LastRoundInfoProcess task;
		
		public void setTask(LastRoundInfoProcess t)
		{
			task = t;
			task.setFragment(this);
		}
		
		@Override
		public void onCreate(Bundle savedInstanceState)
		{
			super.onCreate(savedInstanceState);
			
			setRetainInstance(true);
			
			if(task != null)
			{
				task.execute();
			}
		}
		
		@Override
		public Dialog onCreateDialog(Bundle savedInstanceState)
		{
			ProgressDialog pdia = new ProgressDialog(getActivity());
			pdia.setMessage("Loading your games...");
			pdia.setCanceledOnTouchOutside(false);
			return pdia;
		}
		
		@Override
        public void onDestroyView()
        {
            if (getDialog() != null && getRetainInstance())
                getDialog().setDismissMessage(null);
            super.onDestroyView();
        }
		
		@Override
        public void onDismiss(DialogInterface dialog)
        {
            super.onDismiss(dialog);
            // If true, the thread is interrupted immediately, which may do bad things.
            // If false, it guarantees a result is never returned (onPostExecute() isn't called)
            // but you have to repeatedly call isCancelled() in your doInBackground()
            // function to check if it should exit. For some tasks that might not be feasible.
            if (task != null) {
                task.cancel(false);
            }

            // You don't really need this if you don't want.
            if (getTargetFragment() != null)
                getTargetFragment().onActivityResult(ROUND_HISTORY_FRAGMENT, Activity.RESULT_CANCELED, null);
        }
		
		@Override
        public void onResume()
        {
            super.onResume();
            // This is a little hacky, but we will see if the task has finished while we weren't
            // in this activity, and then we can dismiss ourselves.
            if (task == null)
                dismiss();
        }
		
		// This is also called by the AsyncTask.
        public void taskFinished(Intent data)
        {
            // Make sure we check if it is resumed because we will crash if trying to dismiss the dialog
            // after the user has switched to another app.
            if (isResumed())
                dismiss();

            // If we aren't resumed, setting the task to null will allow us to dimiss ourselves in
            // onResume().
            task = null;

            // Tell the fragment that we are done.
            if (getTargetFragment() != null)
                getTargetFragment().onActivityResult(ROUND_HISTORY_FRAGMENT, Activity.RESULT_OK, data);
        }
	}
	
	protected class LastRoundInfoProcess extends AsyncTask<Void, Void, JSONObject>
	{
		private int lastRound = currentRound -1;
		LastRoundInfoFragment frag;
		
		void setFragment(LastRoundInfoFragment f)
		{
			frag = f;
		}
		
		@Override
		protected JSONObject doInBackground(Void... params)
		{
			Log.e("lastRound", Integer.toString(lastRound));
			UserFunctions uf = new UserFunctions(userKey);
			return uf.fetchRoundHistory(gameKey, lastRound);
		}
		
		protected void onPostExecute(JSONObject json)
		{
			if(frag == null)
			{
				return;
			}
			
			Intent data = new Intent();
			data.putExtra("lastRoundInfo", json.toString());
			frag.taskFinished(data);
		}
	}
	
}
